package com.cy;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.Bean;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;

import java.util.concurrent.atomic.AtomicLong;

@EnableFeignClients
@SpringBootApplication
public class ScaConsumerApplication {
    public static void main(String[] args) {
        SpringApplication.run(ScaConsumerApplication.class, args);
    }

    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }

    @Bean
    @LoadBalanced
    public RestTemplate LoadBalancedRestTemplate() {
        return new RestTemplate();
    }

    @RefreshScope
    @RestController
    public class ConsumerController {
        @Value("${spring.application.name}")
        private String appName;

        @Value("${page.pageSize:10}")
        private Integer pagesize;

        @RequestMapping("/comsumer/doGetPageSize")
        public String doGetPageSize() {
            return "pagesize is  " + pagesize;
        }

        @GetMapping("/consumer/findById")
        @SentinelResource("doFindById")
        public String doFindById(@RequestParam("id") Integer id) {
            return "hot id is " + id;
        }

        @Autowired
        private RestTemplate restTemplate;

        //基于restTemplate 进行远程调用 ,没有负载均衡 没有通过nacos
        @GetMapping("/consumer/doRestEcho1")
        public String doRestEcho1() {
            String url = "http://localhost:8081/provider/echo/" + appName;
            System.out.println("request url:" + url);
            return restTemplate.getForObject(url, String.class);
        }

        @Autowired
        private LoadBalancerClient loadBalancerClient;

        //基于restTemplate 进行远程调用,调用前基于LoadBalancerClient对象去nacos注册中心
        //基于服务名查找服务实例.按照一定算法去选择服务实例

        private AtomicLong atomicLong = new AtomicLong(1);

        @GetMapping("/consumer/doRestEcho2")
        public String doRestEcho2() throws InterruptedException {
            ServiceInstance serviceInstance =
                    loadBalancerClient.choose("sca-provider");
            long num = atomicLong.incrementAndGet();
            if (num % 2 == 0)
                Thread.sleep(200);
            String url = String.format("http://%s:%s/provider/echo/%s",
                    serviceInstance.getHost(),
                    serviceInstance.getPort(),
                    appName);
            System.out.println("requet url:" + url);
            return restTemplate.getForObject(url, String.class);
        }

        @Autowired
        private RestTemplate LoadBalancedRestTemplate;

        /**
         * 基于具备了负载均衡特性的RestTemplate进行远程服务调用,
         * 实现的功能与方式2相同,只是代码编写上相对于第二种方式做了
         * 简化,从效率上会稍微逊色于方式2,因为底层会对请求进行拦截,
         * 拦截到以后再基于loadBalancerClient获取服务实例进行调用.
         */
        @GetMapping("/consumer/doRestEcho3")
        public String doRestEcho3() {
            String url = String.format("http://%s/provider/echo/%s",
                    "sca-provider",
                    appName);
            System.out.println("requet url:" + url);
            return LoadBalancedRestTemplate.getForObject(url, String.class);
        }


    }
}
